package com.jy.datapipeline.common.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.util.ListUtils;
import com.jy.datapipeline.common.commoninterface.EasyExcelExecutionStrategy;
import com.jy.datapipeline.common.exception.GlobalException;
import com.jy.datapipeline.common.util.StringUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.SetUtils;

import java.util.List;
import java.util.Set;

/**
 * @类名 ReadExcelTemplateListener
 * @描述 TODO
 * @作者 白条君
 * @创建日期 2023/8/7 20:40
 * @版本 1.0
 */
@Slf4j
public class ReadExcelTemplateListener<T> extends AnalysisEventListener<T> {
    // 默认行数
    private static int BATCH_COUNT = 100;
    // list用于暂存数据
    private final List<T> cache;
    // lambda调用mapper，
    private final EasyExcelExecutionStrategy easyExcelExecutionStrategy;

    private final Set<Long> ids;

    public ReadExcelTemplateListener(Integer batchCount, EasyExcelExecutionStrategy easyExcelExecutionStrategy) {
        if (batchCount == null) {
            this.cache = ListUtils.newArrayListWithCapacity(BATCH_COUNT);
        } else {
            this.cache = ListUtils.newArrayListWithCapacity(batchCount);
            BATCH_COUNT = batchCount;
        }
        this.easyExcelExecutionStrategy = easyExcelExecutionStrategy;
        this.ids = SetUtils.hashSet();
    }

    @SneakyThrows
    @Override
    public void onException(Exception exception, AnalysisContext context) {
        //回滚之前添加的数据
        if (!CollectionUtils.isEmpty(ids)) {
            easyExcelExecutionStrategy.batchDelete(ids);
            ids.clear();
        }
        //将异常信息通过引用传递传递到controller
        Integer rowIndex = context.readRowHolder().getRowIndex();
        rowIndex = rowIndex + 1;
        log.warn("第" + rowIndex + "条解析失败，终止执行");
        String msg = StringUtil.concat(new StringBuffer(), "error [第", String.valueOf(rowIndex), "行数据:", String.valueOf(exception.getMessage()), "]");
        //抛出异常后监听器终止后续操作
        throw new GlobalException(msg);
    }

    @SneakyThrows
    @Override
    public void invoke(T data, AnalysisContext context) {
        //解析字段
        T t = easyExcelExecutionStrategy.analysisExcelRows(data);
        long rowNum = context.getTotalCount() - 1;
        Integer rowIndex = context.readRowHolder().getRowIndex();
        if (rowNum >= BATCH_COUNT) {
            if (rowIndex <= rowNum - rowNum % BATCH_COUNT) {
                //添加数据暂存到本地缓存
                cache.add(t);
                if (cache.size() >= BATCH_COUNT) {
                    //同步到数据库
                    Set<Long> idList = easyExcelExecutionStrategy.batchSave(cache);
                    //id集合添加到缓存
                    ids.addAll(idList);
                    //清空缓存
                    this.cache.clear();
                }
            } else {
                //同步到数据库
                Long id = easyExcelExecutionStrategy.save(t);
                //暂存id
                ids.add(id);
            }
        } else {
            //同步到数据库
            Long id = easyExcelExecutionStrategy.save(t);
            //暂存id
            ids.add(id);
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        log.info("excel文件读取完毕");
    }
}
